package thread;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.util.Map;
import java.util.Properties;

import model.FileLog;

/**
 * 上传线程
 * 
 * @author 赵庆洋
 * 
 */
public class UpThread extends Thread {

	private Socket socket;

	private Map<Long, FileLog> datas;

	public final static int BUFFER = 1024;

	public UpThread(Socket socket, Map<Long, FileLog> datas) {
		this.socket = socket;
		this.datas = datas;
	}

	/**
	 * 上传方法
	 */
	public void upLoad() {
		try {

			System.out.println("开始上传");

			DataInputStream inStream = new DataInputStream(
					socket.getInputStream());

			// 获取从客户端传来的参数
			String params = inStream.readUTF();

			System.out.println("params:    " + params);

			if (params != null) {
				// 下面从协议数据中读取各种参数值
				String[] items = params.split(";");
				// 要上传文件的长度
				String filelength = items[0]
						.substring(items[0].indexOf("=") + 1);
				// 文件名称(带后缀名)
				String filename = items[1].substring(items[1].indexOf("=") + 1);
				// 上传过的记录的唯一标示符
				String sourceid = items[2].substring(items[2].indexOf("=") + 1);
				// 要上传到电脑的目录路径
				String filepath = items[3].substring(items[3].indexOf("=") + 1);

				// 临时文件名称
				String tempname = filename.substring(0, filename.indexOf("."))
						+ ".tmp";

				// 每个上传记录的唯一标示符
				Long id = System.currentTimeMillis();

				// 下载的记录
				FileLog log = null;

				// 如果手机端有存储上传记录的标示符
				if (null != sourceid && !"".equals(sourceid)) {
					id = Long.valueOf(sourceid);
					// 查找上传的文件是否存在上传记录
					log = find(id);
				}
				// 下载的文件
				File file = null;
				// 临时的文件
				File tempfile = null;
				long position = 0;
				// 如果不存在上传记录 为文件添加记录
				if (log == null) {
					// 目录
					File dir = new File(filepath);
					if (!dir.exists()) {
						dir.mkdirs();
					}
					// 文件
					file = new File(dir, filename);

					tempfile = new File(dir, tempname);
					// 如果文件存在 改名
					if (file.exists()) {
						filename = filename.substring(0,
								filename.indexOf(".") - 1)
								+ dir.listFiles().length
								+ filename.substring(filename.indexOf("."));

						tempname = filename.substring(0, filename.indexOf("."))
								+ ".tmp";

						file = new File(dir, filename);

						tempfile = new File(dir, tempname);

					}
					save(id, file, tempfile);
				}
				// 如果存在记录,读取上次的断点
				else {
					file = new File(log.getPath());
					tempfile = new File(log.getTempPath());
					if (tempfile.exists()) {
						File logFile = new File(file.getParentFile(),
								file.getName() + ".log");
						if (logFile.exists()) {
							Properties properties = new Properties();
							properties.load(new FileInputStream(logFile));
							// 读取断点的位置
							position = Long.valueOf(properties
									.getProperty("length"));
							System.out.println("position:       " + position);
						}
					}

				}

				// 向客户端发送sourceid和断点position
				DataOutputStream dataOutputStream = new DataOutputStream(
						socket.getOutputStream());

				String response = "sourceid=" + id + ";position=" + position;

				System.out.println("position:       " + position);

				// sourceid由服务生成，唯一标识上传的文件，position指示客户端从文件的什么位置开始上传
				dataOutputStream.writeUTF(response);

				dataOutputStream.flush();

				inStream = new DataInputStream(socket.getInputStream());

				// 向硬盘写文件
				RandomAccessFile fileOutStream = new RandomAccessFile(tempfile,
						"rwd");

				if (position == 0) {
					fileOutStream.setLength(Long.valueOf(filelength));
				}

				// 移动到文件指定位置开始写数据
				fileOutStream.seek(position);

				byte[] buffer = new byte[BUFFER];

				int len = -1;

				long length = position;

				while ((len = inStream.read(buffer)) != -1) {
					fileOutStream.write(buffer, 0, len);
					length += len;
					Properties properties = new Properties();
					properties.put("length", String.valueOf(length));
					FileOutputStream logFile = new FileOutputStream(new File(
							file.getParentFile(), file.getName() + ".log"));
					// 实时记录文件的最后保存位置
					properties.store(logFile, null);
					logFile.close();
				}

				if (length == Long.valueOf(filelength)) {
					fileOutStream.close();
					if (tempfile.renameTo(file)) {
						File logFile = new File(file.getParentFile(),
								file.getName() + ".log");
						if (logFile.exists()) {
							logFile.delete();
						}
						delete(id);
						System.out.println("上传成功");
					}
				} else {
					System.out.println("上传中断");
					fileOutStream.close();
				}
				inStream.close();
				dataOutputStream.close();
				file = null;
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public FileLog find(Long sourceid) {
		return datas.get(sourceid);
	}

	// 当文件上传完毕，删除记录
	public void delete(long sourceid) {
		if (datas.containsKey(sourceid))
			datas.remove(sourceid);
	}

	// 保存上传记录
	public void save(Long id, File saveFile, File tempFile) {
		// 日后可以改成通过数据库存放
		FileLog fileLog = new FileLog();
		fileLog.setId(id);
		fileLog.setPath(saveFile.getAbsolutePath());
		fileLog.setTempPath(tempFile.getAbsolutePath());
		datas.put(id, fileLog);
	}

	@Override
	public void run() {
		upLoad();
		super.run();
	}
}
